The Dream Timer
The Idea
My wife tracks how long our baby sleeps in each nap, and how long he is awake between naps, so that we can keep a good sleep schedule and we can predict when he'll be tired in advance. If only she had a stopwatch!
So now I want to build a simple electronic timer for sleeping and waking, with a plastic Sun & Moon on top which light up dimly based on whether the baby is sleeping or waking, and which will have a toggle button to allow switching between Wake mode and Sleep mode. Then, when the baby falls asleep, she'll be able to tap a button and start a timer, which will let her know when 90 mins have passed (or any amount of time) and that the baby can wake up, and vice versa.
Also, she'd like to have a clock in the bedroom when she's sleeping so she can tell if the baby is allowed to wake up yet during the night or if he's just fussy and needs to be put to sleep, so I also want to make this device a clock. But how can it accurately know the time after being turned on? By connecting to the internet and fetching the current time!
Requirements
- Have a timer counting up when a switch is set to TIMER mode.
- Have a toggle button that switched between a SLEEP state and a WAKE state.
- Have a yellow Sun and grey-blue Moon which glow with LEDs based on which mode the circuit is in, SLEEP or WAKE.
- Connect to the internet in CLOCK mode and fetch the current time in EST, then show the time and count up.
- When in CLOCK mode, the yellow & blue LEDs should be off.
- Run on commonly available batteries.
- Run with minimal components, specifically minimal computational components.
The State Diagram

The Circuit
We need a system that moves between two states, which can be altered with the press of one or another button. This is a Button-Triggered Bistable Multivibrator. To acquire a premade circuit of this type, I consult the Holy Bible, a.k.a. The Encyclopedia of Electronic Circuits by Rudolf Graf, Vol. 1. On page 133 of that book we find the following circuit:

In this circuit, touching T1 turns on D1, and touching T2 turns on D2. Therefore, we already have two buttons which control two LEDs, thus, with some later modifications, we have found a candidate to satisfy Requirements (2) and (3). One modification will be made, instead of open metal contacts (T1 and T2), we will use buttons bridging T1 to VCC and T2 to GND.
BOM
| Part | Quantity |
|---|---|
| NE555 Timer | 1 |
| TM1637 6-digit Display (or 4-digit! But I use 6) | 1 |
| 0.1 μF Capacitor | 1 |
| 470 Ω Resistor | 2 |
| 3.3 MΩ Resistor | 2 |
| Blue LED | 1 |
| Yellow LED | 1 |
| M-M jumper wires | |
| SPST Button | 2 |
| Arduino Uno | 1 |
The Arduino Prototype
Validating the Components
I found this great example code on Jason Cox's Github which tests the TM1637 6-Digit Display. There were other code examples and driver libraries which seemed geared towards the 4-digit display, and which failed on the 6-digit; however, this one worked for me. It will (if it works) produce a fun animation showing all the different things you can display on this component.
// TM1637TinyDisplay TEST Sketch for 6-Digit Display
// This is a test sketch for the Arduino TM1637TinyDisplay LED Display library
//
// Author: Jason A. Cox - @jasonacox - https://github.com/jasonacox
// Date: 29 March 2021
//
// Includes
#include <Arduino.h>
#include <TM1637TinyDisplay6.h>
// Module connection pins (Digital Pins)
#define CLK 4
#define DIO 5
// The amount of time (in milliseconds) between tests
#define TEST_DELAY 1000
// Example of manually defining a display pattern
const uint8_t SEG_DONE[] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
SEG_C | SEG_E | SEG_G, // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E
};
// Example animation sequence for showAnimation() Test
// Built with 7-Segment Animator Tool for 6-Digit Displays
// https://jasonacox.github.io/TM1637TinyDisplay/examples/7-segment-animator6.html
const uint8_t ANIMATION[16][6] = {
{ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 0
{ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 }, // Frame 1
{ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, // Frame 2
{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00 }, // Frame 3
{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 }, // Frame 4
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 }, // Frame 5
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 }, // Frame 6
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, // Frame 7
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, // Frame 8
{ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }, // Frame 9
{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }, // Frame 10
{ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }, // Frame 11
{ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }, // Frame 12
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 13
{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 14
{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 } // Frame 15
};
// To save RAM space, we can store the animation sequences in PROGMEM read-only flash memory.
// This requires using the showAnimation_P() function to read from PROGMEM memory space.
const uint8_t ANIMATION2[92][6] PROGMEM = {
{ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 0
{ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 }, // Frame 1
{ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, // Frame 2
{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00 }, // Frame 3
{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 }, // Frame 4
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 }, // Frame 5
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 }, // Frame 6
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, // Frame 7
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, // Frame 8
{ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }, // Frame 9
{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }, // Frame 10
{ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }, // Frame 11
{ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }, // Frame 12
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 13
{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 14
{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 15
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 16
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 17
{ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00 }, // Frame 18
{ 0x80, 0x80, 0x80, 0x00, 0x00, 0x00 }, // Frame 19
{ 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }, // Frame 20
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x00 }, // Frame 21
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, // Frame 22
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x81 }, // Frame 23
{ 0x80, 0x80, 0x80, 0x80, 0x81, 0x80 }, // Frame 24
{ 0x80, 0x80, 0x80, 0x81, 0x80, 0x80 }, // Frame 25
{ 0x80, 0x80, 0x81, 0x80, 0x80, 0x80 }, // Frame 26
{ 0x80, 0x81, 0x80, 0x80, 0x80, 0x80 }, // Frame 27
{ 0x81, 0x80, 0x80, 0x80, 0x80, 0x80 }, // Frame 28
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, // Frame 29
{ 0xb0, 0x80, 0x80, 0x80, 0x80, 0x80 }, // Frame 30
{ 0x06, 0x80, 0x80, 0x80, 0x80, 0x80 }, // Frame 31
{ 0x00, 0xb0, 0x80, 0x80, 0x80, 0x80 }, // Frame 32
{ 0x00, 0x06, 0x80, 0x80, 0x80, 0x80 }, // Frame 33
{ 0x00, 0x00, 0xb0, 0x80, 0x80, 0x80 }, // Frame 34
{ 0x00, 0x00, 0x06, 0x80, 0x80, 0x80 }, // Frame 35
{ 0x00, 0x00, 0x00, 0xb0, 0x80, 0x80 }, // Frame 36
{ 0x00, 0x00, 0x00, 0x06, 0x80, 0x80 }, // Frame 37
{ 0x00, 0x00, 0x00, 0x00, 0xb0, 0x80 }, // Frame 38
{ 0x00, 0x00, 0x00, 0x00, 0x06, 0x80 }, // Frame 39
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0 }, // Frame 40
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 }, // Frame 41
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 42
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }, // Frame 43
{ 0x00, 0x00, 0x00, 0x00, 0x46, 0x00 }, // Frame 44
{ 0x00, 0x00, 0x00, 0x46, 0x00, 0x00 }, // Frame 45
{ 0x00, 0x00, 0x46, 0x00, 0x00, 0x00 }, // Frame 46
{ 0x00, 0x46, 0x00, 0x00, 0x00, 0x00 }, // Frame 47
{ 0x46, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 48
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 49
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 50
{ 0x40, 0x01, 0x00, 0x00, 0x00, 0x00 }, // Frame 51
{ 0x08, 0x40, 0x01, 0x00, 0x00, 0x00 }, // Frame 52
{ 0x01, 0x08, 0x40, 0x01, 0x00, 0x00 }, // Frame 53
{ 0x40, 0x01, 0x08, 0x40, 0x01, 0x00 }, // Frame 54
{ 0x08, 0x40, 0x01, 0x08, 0x40, 0x01 }, // Frame 55
{ 0x00, 0x08, 0x40, 0x01, 0x08, 0x40 }, // Frame 56
{ 0x00, 0x00, 0x08, 0x40, 0x01, 0x08 }, // Frame 57
{ 0x00, 0x00, 0x00, 0x08, 0x40, 0x01 }, // Frame 58
{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x40 }, // Frame 59
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 }, // Frame 60
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 61
{ 0x4f, 0x00, 0x00, 0x00, 0x00, 0x66 }, // Frame 62
{ 0x5b, 0x4f, 0x00, 0x00, 0x66, 0x6d }, // Frame 63
{ 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d }, // Frame 64
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 65
{ 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d }, // Frame 66
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 67
{ 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d }, // Frame 68
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 69
{ 0x63, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 70
{ 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00 }, // Frame 71
{ 0x00, 0x00, 0x63, 0x00, 0x00, 0x00 }, // Frame 72
{ 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00 }, // Frame 73
{ 0x00, 0x00, 0x00, 0x00, 0x63, 0x00 }, // Frame 74
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c }, // Frame 75
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 76
{ 0x79, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Frame 77
{ 0x54, 0x79, 0x00, 0x00, 0x00, 0x00 }, // Frame 78
{ 0x5c, 0x54, 0x79, 0x00, 0x00, 0x00 }, // Frame 79
{ 0x5e, 0x5c, 0x54, 0x79, 0x00, 0x00 }, // Frame 80
{ 0x00, 0x5e, 0x5c, 0x54, 0x79, 0x00 }, // Frame 81
{ 0x00, 0x5e, 0x5c, 0x54, 0x79, 0x00 }, // Frame 82
{ 0x00, 0x4e, 0x5c, 0x54, 0x79, 0x00 }, // Frame 83
{ 0x00, 0x06, 0x5c, 0x54, 0x30, 0x00 }, // Frame 84
{ 0x00, 0x00, 0x5c, 0x54, 0x00, 0x00 }, // Frame 85
{ 0x00, 0x00, 0x4c, 0x50, 0x00, 0x00 }, // Frame 86
{ 0x00, 0x00, 0x04, 0x10, 0x00, 0x00 }, // Frame 87
{ 0x00, 0x00, 0x10, 0x04, 0x00, 0x00 }, // Frame 88
{ 0x00, 0x10, 0x00, 0x00, 0x04, 0x00 }, // Frame 89
{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x04 }, // Frame 90
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // Frame 91
};
// Text string constants can be stored in PROGMEM read-only flash memory.
// This requires using the showString_P() function to read from PROGMEM memory space.
// PROGMEM space strings are globally defined.
const PROGMEM char FlashString[] = "Flash Test - 1234567890";
const PROGMEM char FlashString2[] = "good";
TM1637TinyDisplay6 display(CLK, DIO);
void setup()
{
display.begin();
}
void loop()
{
int k;
uint8_t data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; // Test Pattern - All
uint8_t blank[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Test Pattern - Blank
display.setBrightness(BRIGHT_HIGH);
// Announce Testing
display.showString("test");
delay(TEST_DELAY);
// Test Basics
display.showString("digits"); // 6 digits
delay(TEST_DELAY);
display.showNumber(1234567); // overflow
delay(TEST_DELAY);
display.showNumber(123.456); // decimal
delay(TEST_DELAY);
display.showNumber(123456.0); // decimal
delay(TEST_DELAY);
display.showNumber(1234567.0);// decimal
delay(TEST_DELAY);
display.showNumber(PI); // decimal
delay(TEST_DELAY);
// All segments on
display.setSegments(data);
delay(TEST_DELAY);
// Test setting different digits
data[0] = display.encodeDigit(1);
data[1] = display.encodeDigit(2);
data[2] = display.encodeDigit(3);
data[3] = display.encodeDigit(4);
data[4] = display.encodeDigit(5);
data[5] = display.encodeDigit(6);
display.setSegments(data);
delay(TEST_DELAY);
// Test display splitting with position
display.clear();
display.setSegments(data + 2, 2, 2); // Length 2, Position 2
delay(TEST_DELAY);
display.clear();
display.setSegments(data + 2, 2, 1); // Length 2, Position 1
delay(TEST_DELAY);
display.clear();
display.setSegments(data + 1, 3, 1); // Length 3, Position 1
delay(TEST_DELAY);
// Test decimal numbers with/without leading zeros in different positions
display.showNumber(0, false); // Expect: ___0
delay(TEST_DELAY);
display.showNumber(0, true); // Expect: 0000
delay(TEST_DELAY);
display.showNumber(1, false); // Expect: ___1
delay(TEST_DELAY);
display.showNumber(1, true); // Expect: 0001
delay(TEST_DELAY);
display.showNumber(301, false); // Expect: _301
delay(TEST_DELAY);
display.showNumber(301, true); // Expect: 0301
delay(TEST_DELAY);
display.showNumber(3001, false); // Expect: 3001
delay(TEST_DELAY);
display.showNumber(30001, false); // Expect: 30001
delay(TEST_DELAY);
display.showNumber(300001, false); // Expect: 300001
delay(TEST_DELAY);
display.clear();
display.showNumber(14, false, 2, 1); // Expect: _14_
delay(TEST_DELAY);
display.clear();
display.showNumber(4, true, 2, 2); // Expect: __04
delay(TEST_DELAY);
display.showNumber(-1, false); // Expect: __-1
delay(TEST_DELAY);
display.showNumber(-12); // Expect: _-12
delay(TEST_DELAY);
display.showNumber(-999); // Expect: -999
delay(TEST_DELAY);
display.showNumber(-9999); // Expect: -9999
delay(TEST_DELAY);
display.showNumber(-99999); // Expect: -99999
delay(TEST_DELAY);
display.clear();
display.showNumber(-5, false, 3, 0); // Expect: _-5_
delay(TEST_DELAY);
display.showNumberHex(0xf1af); // Expect: f1Af
delay(TEST_DELAY);
display.showNumberHex(0x2c); // Expect: __2C
delay(TEST_DELAY);
display.showNumberHex(0xd1, 0, true); // Expect: 00d1
delay(TEST_DELAY);
display.clear();
display.showNumberHex(0xd1, 0, true, 2); // Expect: d1__
delay(TEST_DELAY);
// Floating point tests
display.showNumber(1.234); // Floating point number
delay(TEST_DELAY);
display.showNumber(1.234, 2); // Format to 2 decimal places
delay(TEST_DELAY);
display.showNumber(-1.23456); // Negative floating point number
delay(TEST_DELAY);
display.showNumber(-0.5); // Zero prefix floating point number
delay(TEST_DELAY);
display.showNumber(0.4);
delay(TEST_DELAY);
display.showNumber(1005.3);
delay(TEST_DELAY);
display.showNumber(1000005.3); // Overflow test
delay(TEST_DELAY);
display.showNumber(0.52345, 1);
delay(TEST_DELAY);
display.showNumber(0.255, 2); // Test rounding up
delay(TEST_DELAY);
display.clear();
display.showString("\xB0", 1, 5); // Test with suffix
display.showNumber(12.3456, 4, 5, 0);
delay(TEST_DELAY);
for (int x = -100; x < 100; x = x + 1) { // Count
display.showNumber((float)x / 10.0);
}
// Test all the dots
for (k = 0; k <= 6; k++) {
display.showNumberDec(0, (0x80 >> k), true);
delay(TEST_DELAY);
}
uint8_t dots = 0b10101000;
for (int x = 0; x < 8; x++) {
display.showNumberDec(987654, dots >> x, false); // Expect: 3.03.03.
delay(TEST_DELAY);
}
dots = 0b11111100;
for (int x = 0; x < 8; x++) {
display.showNumberDec(123456, dots << x, false); // Expect: 1.2.3.4.5.6.
delay(TEST_DELAY);
}
// Test Brightness Levels
for (k = 0; k < 6; k++)
data[k] = 0xff;
for (k = 0; k < 7; k++) {
display.setBrightness(k);
display.setSegments(data);
delay(TEST_DELAY);
}
// Test Display On/Off
for (k = 0; k < 4; k++) {
display.setBrightness(7, false); // Turn off
display.setSegments(data);
delay(TEST_DELAY);
display.setBrightness(7, true); // Turn on
display.setSegments(data);
delay(TEST_DELAY);
}
// Test Horizontal Level Meter
for (int count = 0; count < 3; count++) {
for (int x = 0; x <= 100; x = x + 10) {
display.showLevel(x, true);
delay(20);
}
for (int x = 100; x > 0; x = x - 10) {
display.showLevel(x, true);
delay(20);
}
}
// Test Vertical Level Meter
for (int count = 0; count < 3; count++) {
for (int x = 0; x <= 100; x = x + 10) {
display.showLevel(x, false);
delay(20);
}
for (int x = 100; x > 0; x = x - 10) {
display.showLevel(x, false);
delay(20);
}
}
// Test Numbers and Strings Using Positions
display.clear();
char degree[] = "\xB0";
display.showString(degree, 1, 5); // Position 5 (right) and 1 char length
for (int x = -50; x < 1500; x = x + 5) {
display.showNumber(x, false, 5, 0); // Postion 0 (left) and 5 char length
delay(10);
}
delay(TEST_DELAY);
// Test String Display
display.clear();
display.showString("String Test 1234"); // Test literal string
delay(TEST_DELAY);
display.clear();
char stringb[10]; // Test dynamic string
sprintf(stringb, "25%cC", '\xB0'); // Display 25 + degree symbol + C
display.showString(stringb);
delay(TEST_DELAY);
display.clear(); // Long string test
display.showString("abcdefghijklmnopqrstuvwxyz.-=ABCDEFGHIJKLMNOPQRSTUVWXYZ");
delay(TEST_DELAY);
// Test Strings in PROGMEM flash memory
display.showString_P(FlashString);
delay(1000);
display.showString_P(FlashString2);
delay(1000);
// Animation Sequence Test in SRAM - Run 3 times
display.clear();
for (int count = 0; count < 3; count++) {
display.showAnimation(ANIMATION, FRAMES(ANIMATION), TIME_MS(10));
}
display.clear();
delay(TEST_DELAY);
// Animation Sequence Test in PROGMEM flash memory
display.clear();
display.showAnimation_P(ANIMATION2, FRAMES(ANIMATION2), TIME_MS(50));
// Done!
display.clear();
display.showString("The");
delay(TEST_DELAY);
display.showString(" End");
delay(TEST_DELAY);
display.setSegments(SEG_DONE);
delay(TEST_DELAY * 5);
}
Test Code
Basic Display Counter
The following code programs the counter component to count up from zero in seconds, minutes, and hours. Hopefully you can see very clearly what is happening here: I create three counters that increment each second and minute and hour, which then become the proper digits to display, and are written to an array where each index corresponds to one digit on the counter.
#include <Arduino.h>
#include <TM1637TinyDisplay6.h>
// TM1637 pins
#define CLK 4
#define DIO 5
// Count interval (milliseconds)
#define COUNT_DELAY 1000
TM1637TinyDisplay6 display(CLK, DIO);
int seconds = 0, minutes = 0, hours = 0;
uint8_t data[6];
void setup() {
display.begin();
display.setBrightness(BRIGHT_HIGH);
display.clear();
}
void loop() {
// The division and modulo's here are used to separate the two digits of a base 10
// number, e.g. if hours = 15, data[0] = 1 and data[1] = 5.
data[0] = display.encodeDigit(hours / 10);
data[1] = display.encodeDigit(hours % 10);
data[2] = display.encodeDigit(minutes / 10);
data[3] = display.encodeDigit(minutes % 10);
data[4] = display.encodeDigit(seconds / 10);
data[5] = display.encodeDigit(seconds % 10);
display.setSegments(data, 6, 0); // This method pushes our data to the TM1637
seconds++;
if (seconds >= 60) {
minutes++;
seconds = 0;
}
if (minutes >= 60) {
hours++;
minutes = 0;
}
delay(COUNT_DELAY);
}
Wifi Helper Functions
The ESP32 can easily connect to a Wifi network with provided credentials:
#include <WiFi.h>
const char* WIFI_SSID = "network-name";
const char* WIFI_PASS = "network-pass";
bool wifiConnected = false;
const unsigned long WIFI_CONNECT_TIMEOUT_MS = 10000;
void setup() {
Serial.begin(115200);
delay(50);
connectToWifi();
}
void loop() {}
void connectToWifi() {
// If wifi is already connected, move on
if (WiFi.status() == WL_CONNECTED) {
wifiConnected = true;
Serial.println("[WiFi] Already connected");
return;
}
// Begin wifi connection attempt
Serial.printf("[WiFi] Connecting to '%s' ...\n", WIFI_SSID);
WiFi.mode(WIFI_STA); // Enable wifi transmitting.
WiFi.begin(WIFI_SSID, WIFI_PASS);
// Logging: while connection is pending, print dots to Serial
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && (millis() - start) < WIFI_CONNECT_TIMEOUT_MS) {
delay(200);
Serial.print(".");
}
Serial.println();
// If success, print success message. If failure, print failure and disconnect.
if (WiFi.status() == WL_CONNECTED) {
wifiConnected = true;
Serial.print("[WiFi] Connected, IP=");
Serial.println(WiFi.localIP());
} else {
wifiConnected = false;
Serial.println("[WiFi] Failed to connect (timeout)");
// optionally disable Wi-Fi to save power if not connected
WiFi.disconnect(true);
}
}
// Disconnect and turn off wifi transmission altogether
void disconnectWifi() {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("[WiFi] Disconnecting to save power (TIMER mode)");
}
wifiConnected = false;
WiFi.disconnect(true); // disconnect and erase credentials from driver to reduce radio activity
WiFi.mode(WIFI_OFF);
}